package com.weaving.monitor.service;

import com.weaving.monitor.entity.Machine;
import com.weaving.monitor.entity.PendingPlan;
import com.weaving.monitor.entity.RedisMachineData;
import com.weaving.monitor.mapper.MachineMapper;
import com.weaving.monitor.mapper.PendingPlanMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

/**
 * 定时任务服务类
 * 负责定期计算和更新数据
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class ScheduleTaskService {

    private final MachineMapper machineMapper;
    private final PendingPlanMapper pendingPlanMapper;
    private final RedisService redisService;
    
    /** 下轮计划查询服务，通过字段注入 */
    private final NextPlanService nextPlanService;
    /** 梳栉花型查询服务，通过字段注入 */
    @Autowired
    private PatternService patternService;


    /**
     * 定时任务：计算并更新机器数据
     * 每10秒执行一次
     */
    @Scheduled(fixedRate = 600000) // 10秒 = 10000毫秒
    public void updateMachineData() {
        log.info("开始执行机器数据更新定时任务...");
        
        try {
            // 生成模拟机器数据
            List<Machine> machines = generateMachineData();
            
            // 逐个检查并更新或插入数据
            for (Machine machine : machines) {
                Machine existingMachine = machineMapper.selectByMachineNumber(machine.getMachineNumber());
                if (existingMachine != null) {
                    // 如果存在则更新
                    machine.setId(existingMachine.getId());
                    machineMapper.updateMachine(machine);
                    log.debug("更新机器 {} 的数据", machine.getMachineNumber());
                } else {
                    // 如果不存在则插入
                    machineMapper.insert(machine);
                    log.debug("插入机器 {} 的数据", machine.getMachineNumber());
                }
            }
            
            log.info("机器数据更新完成，共处理 {} 台机器", machines.size());
            
        } catch (Exception e) {
            log.error("机器数据更新定时任务执行失败", e);
        }
    }

    /**
     * 定时任务：计算并更新待翻品种计划数据
     * 每30秒执行一次
     */
    @Scheduled(fixedRate = 300000) // 30秒 = 30000毫秒
    public void updatePendingPlanData() {
        log.info("开始执行待翻品种计划数据更新定时任务...");
        
        try {
            // 为每台机器获取待翻品种数据
            for (int machineNumber = 1; machineNumber <= 25; machineNumber++) {
                try {
                    // 构建机器ID格式
                    String machineId = "J" + String.format("%03d", machineNumber);
                    
                    // 先删除当前机器的所有待翻品种计划
                    pendingPlanMapper.deleteByMachineNumber(machineNumber);
                    log.debug("删除机器 {} 的所有待翻品种计划", machineNumber);
                    
                    // 从数据库查询待翻品种数据
                    List<String> pendingPlanNames = pendingPlanMapper.selectPendingPlansByMachineId(machineId);
                    
                    // 插入前三条数据
                    for (int i = 0; i < Math.min(pendingPlanNames.size(), 3); i++) {
                        PendingPlan plan = new PendingPlan();
                        plan.setMachineNumber(machineNumber);
                        plan.setRoundNumber(i + 1);
                        plan.setPlanDetails(pendingPlanNames.get(i));
                        plan.setPriority(1 + i); // 优先级递增
                        
                        pendingPlanMapper.insert(plan);
                        log.debug("插入机器 {} 轮次 {} 的计划: {}", machineNumber, i + 1, pendingPlanNames.get(i));
                    }
                    
                } catch (Exception e) {
                    log.error("处理机器 {} 的待翻品种计划时发生异常", machineNumber, e);
                }
            }
            
            log.info("待翻品种计划数据更新完成");
            
        } catch (Exception e) {
            log.error("待翻品种计划数据更新定时任务执行失败", e);
        }
    }

    /**
     * 生成机器数据（从Redis获取实时数据）
     */
    private List<Machine> generateMachineData() {
        List<Machine> machines = new ArrayList<>();
        
        // 检查Redis连接
        if (!redisService.isRedisConnected()) {
            log.warn("Redis连接异常，使用模拟数据");
            return generateMockMachineData();
        }
        
        // 获取Redis中所有机器数据的key
        java.util.Set<String> machineKeys = redisService.getAllMachineKeys();
        log.info("从Redis获取到 {} 台机器的数据", machineKeys.size());
        
        // 处理每台机器的数据
        for (String key : machineKeys) {
            try {
                // 从key中提取机器号，格式：knitting_snapshot_J001
                String machineNumberStr = key.substring(key.lastIndexOf("J") + 1);

                Integer machineNumber = Integer.parseInt(machineNumberStr);
                
                // 从Redis获取机器实时数据
                RedisMachineData redisData = redisService.getMachineData(machineNumber);
                if (redisData == null) {
                    log.warn("机器 {} 的Redis数据为空，跳过", machineNumber);
                    continue;
                }
                
                // 将Redis数据转换为Machine实体
                Machine machine = convertRedisDataToMachine(redisData, machineNumber);
                String machineId = "J" + String.format("%03d", machine.getMachineNumber());
                machine.setL1Pattern(patternService.getPatternByMachineAndGbNum(machineId, 1));
                machine.setL1Remaining(machine.getL1Remaining());
                machine.setL2Pattern(patternService.getPatternByMachineAndGbNum(machineId, 2));
                machine.setL2Remaining(machine.getL2Remaining());
                machine.setL3Pattern(patternService.getPatternByMachineAndGbNum(machineId, 3));
                machine.setL3Remaining(machine.getL3Remaining());
                machine.setL4Pattern(patternService.getPatternByMachineAndGbNum(machineId, 4));
                machine.setL4Remaining(machine.getL4Remaining());

                // 从数据库查询当前生产物料类型
                String currentMatType = nextPlanService.getCurrentMatTypeByMachineId(machineId);
                machine.setCurrentMatTypeName(currentMatType);

                // 从数据库获取机台gb轴类型
                Machine existingMachine = machineMapper.selectByMachineNumber(machineNumber);
                if (existingMachine != null && existingMachine.getMachineGbType() != null) {
                    machine.setMachineGbType(existingMachine.getMachineGbType());
                } else {
                    // 如果数据库中没有记录或字段为空，使用默认值1
                    machine.setMachineGbType(1);
                }

                // 根据machine_gb_type进行pattern和remaining值的交换
                adjustPatternAndRemainingByGbType(machine);

                machines.add(machine);
                
                log.debug("成功处理机器 {} 的Redis数据", machineNumber);
                
            } catch (Exception e) {
                log.error("处理机器key {} 时发生异常", key, e);
            }
        }
        
        // 如果没有从Redis获取到数据，使用模拟数据
        if (machines.isEmpty()) {
            log.warn("未从Redis获取到有效数据，使用模拟数据");
            return generateMockMachineData();
        }
        
        return machines;
    }
    
    /**
     * 将Redis数据转换为Machine实体
     */
    private Machine convertRedisDataToMachine(RedisMachineData redisData, Integer machineNumber) {
        Machine machine = new Machine();
        machine.setMachineNumber(machineNumber);
        
        // 设置机器型号（根据实际情况调整）
        machine.setModel("KS" + (3 + (machineNumber % 3)));
        
        // 设置布长（从Redis的currentMeter获取）
        machine.setFabricLength(redisData.getCurrentMeter() != null ? redisData.getCurrentMeter().doubleValue() : 0.0);

        // 设置操作员（从Redis的staffCardID获取）
        machine.setOperator(redisData.getStaffCardID() != null ? redisData.getStaffCardID() : "未知");
        
        // 设置速度（从Redis的mainRollerSpeed获取）
        machine.setSpeed(redisData.getMainRollerSpeed() != null ? redisData.getMainRollerSpeed() : 0);
        
        // 设置梳栉图案和剩余时间（从Redis的gb1-gb4相关字段获取）
//        machine.setL1Pattern("PATTERN-" + (100 + machineNumber * 10));
        machine.setL1Remaining(redisData.getGb1RemainHour() != null ? redisData.getGb1RemainHour().doubleValue() : 0.0);
        
//        machine.setL2Pattern("PATTERN-" + (200 + machineNumber * 10));
        machine.setL2Remaining(redisData.getGb2RemainHour() != null ? redisData.getGb2RemainHour().doubleValue() : 0.0);
        
//        machine.setL3Pattern("PATTERN-" + (300 + machineNumber * 10));
        machine.setL3Remaining(redisData.getGb3RemainHour() != null ? redisData.getGb3RemainHour().doubleValue() : 0.0);
        
//        machine.setL4Pattern("PATTERN-" + (400 + machineNumber * 10));
        machine.setL4Remaining(redisData.getGb4RemainHour() != null ? redisData.getGb4RemainHour().doubleValue() : 0.0);
        
        // 从数据库查询下轮计划
        String machineId = "J" + String.format("%03d", machineNumber);
        String nextPlan = nextPlanService.getNextPlanByMachineId(machineId);
        machine.setNextPlan(nextPlan);
        
        // 从数据库查询当前生产物料类型
        String currentMatType = nextPlanService.getCurrentMatTypeByMachineId(machineId);
        machine.setCurrentMatTypeName(currentMatType);
        
        // 设置机器状态（根据machineStatus字段）
        String status;
        if (redisData.getMachineStatus() != null) {
            switch (redisData.getMachineStatus()) {
                case 1:
                    status = "RUNNING";
                    break;
                case 0:
                    status = "STOPPED";
                    break;
                default:
                    status = "DISCONNECT";
                    break;
            }
        } else {
            status = "unknown";
        }
        machine.setStatus(status);
        
        // 设置机台gb轴类型，默认值为1

        machine.setMachineGbType(1);
        
        // 设置最后更新时间
        machine.setLastUpdated(new Date());
        
        return machine;
    }
    
    /**
     * 生成模拟机器数据（备用方案）
     */
    private List<Machine> generateMockMachineData() {
        List<Machine> machines = new ArrayList<>();
        Random random = new Random();
        
        // 生成25台机器的数据
        for (int i = 1; i <= 25; i++) {
            Machine machine = new Machine();
            machine.setMachineNumber(i);
            
            // 随机状态
            String[] statuses = {"RUNNING", "STOPPED", "MAINTENANCE", "ERROR"};
            machine.setStatus(statuses[random.nextInt(statuses.length)]);
            
            // 随机布长 (1000-5000米)
            machine.setFabricLength(0.0);
            
            // 随机车速 (800-1200转/分)
            machine.setSpeed(800 + random.nextInt(400));
            
            // 随机工人
            String[] operators = {"张三", "李四", "王五", "赵六", "钱七"};
            machine.setOperator(operators[random.nextInt(operators.length)]);
            
            // 随机L1-L4数据
            machine.setL1Pattern("PATTERN-" + (100 + random.nextInt(900)));
            machine.setL1Remaining((double)(1 + random.nextInt(20)));
            
            machine.setL2Pattern("PATTERN-" + (200 + random.nextInt(800)));
            machine.setL2Remaining((double)(1 + random.nextInt(20)));
            
            machine.setL3Pattern("PATTERN-" + (300 + random.nextInt(700)));
            machine.setL3Remaining((double)(1 + random.nextInt(20)));
            
            machine.setL4Pattern("PATTERN-" + (400 + random.nextInt(600)));
            machine.setL4Remaining((double)(1 + random.nextInt(20)));
            
            // 从数据库查询下轮计划
            String machineId = "J" + String.format("%03d", i);
            String nextPlan = nextPlanService.getNextPlanByMachineId(machineId);
            machine.setNextPlan(nextPlan);
            
            // 从数据库查询当前生产物料类型
            String currentMatType = nextPlanService.getCurrentMatTypeByMachineId(machineId);
            machine.setCurrentMatTypeName(currentMatType);
            
            // 从数据库获取机台gb轴类型
            Machine existingMachine = machineMapper.selectByMachineNumber(i);
            if (existingMachine != null && existingMachine.getMachineGbType() != null) {
                machine.setMachineGbType(existingMachine.getMachineGbType());
            } else {
                // 如果数据库中没有记录或字段为空，使用默认值1
                machine.setMachineGbType(1);
            }
            
            // 根据machine_gb_type进行pattern和remaining值的交换
            adjustPatternAndRemainingByGbType(machine);
            
            // 设置最后更新时间
            machine.setLastUpdated(new Date());
            
            machines.add(machine);
        }
        
        return machines;
    }

    /**
     * 根据machine_gb_type调整pattern和remaining值
     * 
     * 功能说明：
     * 1. 当machine_gb_type=3时，l1Pattern和l3Pattern值换一下，l1Remaining和l3Remaining值换一下
     * 2. 当machine_gb_type=4时，l1Pattern和l4Pattern值换一下，l1Remaining和l4Remaining值换一下，
     *    l2Pattern和l3Pattern值换一下，l2Remaining和l3Remaining换一下
     * 
     * @param machine 机器对象
     */
    private void adjustPatternAndRemainingByGbType(Machine machine) {
        Integer gbType = machine.getMachineGbType();
        if (gbType == null) {
            gbType = 1; // 默认值
        }
        
        switch (gbType) {
            case 3:
                // l1Pattern和l3Pattern值换一下，l1Remaining和l3Remaining值换一下
                swapPatternAndRemaining(machine, 1, 3);
                break;
            case 4:
                // l1Pattern和l4Pattern值换一下，l1Remaining和l4Remaining值换一下
                swapPatternAndRemaining(machine, 1, 4);
                // l2Pattern和l3Pattern值换一下，l2Remaining和l3Remaining换一下
                swapPatternAndRemaining(machine, 2, 3);
                break;
            default:
                // 其他类型不做调整
                break;
        }
    }
    
    /**
     * 交换两个梳栉的pattern和remaining值
     * 
     * @param machine 机器对象
     * @param gb1 第一个梳栉编号
     * @param gb2 第二个梳栉编号
     */
    private void swapPatternAndRemaining(Machine machine, int gb1, int gb2) {
        String tempPattern;
        Double tempRemaining;
        
        switch (gb1) {
            case 1:
                switch (gb2) {
                    case 3:
                        // 交换L1和L3
                        tempPattern = machine.getL1Pattern();
                        tempRemaining = machine.getL1Remaining();
                        machine.setL1Pattern(machine.getL3Pattern());
                        machine.setL1Remaining(machine.getL3Remaining());
                        machine.setL3Pattern(tempPattern);
                        machine.setL3Remaining(tempRemaining);
                        break;
                    case 4:
                        // 交换L1和L4
                        tempPattern = machine.getL1Pattern();
                        tempRemaining = machine.getL1Remaining();
                        machine.setL1Pattern(machine.getL4Pattern());
                        machine.setL1Remaining(machine.getL4Remaining());
                        machine.setL4Pattern(tempPattern);
                        machine.setL4Remaining(tempRemaining);
                        break;
                }
                break;
            case 2:
                switch (gb2) {
                    case 3:
                        // 交换L2和L3
                        tempPattern = machine.getL2Pattern();
                        tempRemaining = machine.getL2Remaining();
                        machine.setL2Pattern(machine.getL3Pattern());
                        machine.setL2Remaining(machine.getL3Remaining());
                        machine.setL3Pattern(tempPattern);
                        machine.setL3Remaining(tempRemaining);
                        break;
                }
                break;
        }
    }


} 